
jsx3.lang.Class.defineClass("ux.megatron.util.ValidationManager", null, null,
    function(manager) {
        
        manager._validators = {};
        manager._errorMsgs  = {};

        var regString = {
            Email     : /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
            //Phone   : /^((\(\d{3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-|0\d{2,3})?[1-9]\d{6,7}$/,
            Phone     : /^0\d{2,3}[1-9]\d{6,7}$/,
            Mobile    : /^((\(\d{3}\))|(\d{3}\-))?1[35]\d{9}$/,
            Currency  : /^\d+(\.\d+)?$/,
            Number    : /^\d+$/,
            Integer   : /^[-\+]?\d+$/,
            Double    : /^[-\+]?\d+(\.\d+)?$/,
            English   : /^[A-Za-z]+$/,
            Chinese   : /^[\u0391-\uFFE5]+$/,
            Zip       : /^\d{6}$/
        };

        manager.addValidator = function(name, validator, message) {
            this._validators[name] = validator;
            this._errorMsgs [name] = message;
        };

        manager.getValidator = function(name) {
            if(regString[name]) {
                return this.getRegExpValidator(name);
            }
            return this["validate"+name] || this._validators[name];
        };

        manager.getRegExpValidator = function(name) {
            return function(val) {
                if(manager.isNullValue(val)) { return null; }
                if(!regString[name].test(val)) {
                    return manager.getErrorMessage(name);
                }
                return null;
            };
        };

        manager.getErrorMessage = function(name) {
            return this._errorMsgs[name] || ux.megatron.Main.getServer().getDynamicProperty("@ValidationError "+ name);
        };

        manager.validateRequired = function(val) {
            if(!val || (val === "")) { return manager.getErrorMessage("Required"); }
            return null;
        };

        manager.validateNumeric = function(val) {
            if(manager.isNullValue(val)) { return null; }
            if(!manager.isNumeric(val)) { return manager.getErrorMessage("Numeric"); }
            return null;
        };

        manager.validatePostiveNumberic = function(val) {
            if(manager.isNullValue(val)) { return null; }
            if(!manager.isPositiveNumeric(val)) { return manager.getErrorMessage("PostiveNumberic"); }
            return null;
        };

        manager.validatePositiveFloatingPoint = function(val) {
            if(manager.isNullValue(val)) { return null; }
            if(!manager.isPositiveFloatingPoint(val)) { return manager.getErrorMessage("PostiveNumberic"); }
            return null;
        };

        manager.validateURL = function(val) {
            if(manager.isNullValue(val)) { return null; }
            var regURL = new RegExp("^(\\w+):\\/\\/([^/:]+)(:\\d+){0,1}$", "i");
            if (!regURL.test(val)) { 
                return manager.getErrorMessage("URL");
            } else {
                return null;
            }
        };

        manager.validateIDCard = function(val) {
            if(manager.isNullValue(val)) { return null; }
            if(!/^(\d{17}(\d|x)|(\d{15}))$/i.test(val)){ 
                return manager.getErrorMessage("IDCard"); 
            } else {
                return manager.isIDCard(val);
            }

        };

        manager.validateMaxLength = function(val, len) {
            if(manager.isNullValue(val)) { return null; }
            len = len || 200;
            if(manager.getLength(val) > len) {
                return manager.getErrorMessage("MaxLength") + len;
            } else {
                return null;
            }
        };

        manager.validateRegExp = function(val, reg) {
            if(manager.isNullValue(val)) { return null; }
            var regExp = new RegExp(reg, "i");
            if (!regExp.test(val)) { 
                return manager.getErrorMessage("RegExp") + reg;
            } else {
                return null;
            }            
        };

        manager.getLength = function(val) {
           return val.toString().replace(/[^\x00-\xff]/g,"**").length; 
        };

        manager.isIDCard = function(sId) {
            var citys = [0,
                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                11,12,13,14,15, 0, 0, 0, 0, 0,
                21,22,23, 0, 0, 0, 0, 0, 0, 0,
                31,32,33,34,35,36,37, 0, 0, 0,
                41,42,43,44,45,46, 0, 0, 0,50,
                51,52,53,54, 0, 0, 0, 0, 0, 0,
                61,62,63,64,65, 0, 0, 0, 0, 0,
                71, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                81,82, 0, 0, 0, 0, 0, 0, 0, 0];
            
            var longTypeId = (sId.length==18), dateString, sum=0;

            sId=sId.replace(/[xX]$/i,"a");
            if(!citys[parseInt(sId.substr(0,2))]) {
                return manager.getErrorMessage("IDCard InvaildCity");
            }
            
            dateString = longTypeId ? sId.substr(6,8) : "19" + sId.substr(6,6);
            if(!manager.isDateString(dateString)) {
                return manager.getErrorMessage("IDCard InvaildBirthday");
            }

            if(longTypeId) {
                for(var i=17;i>=0;i--) {
                    sum += (Math.pow(2,i)%11)*parseInt(sId.charAt(17-i),11)  
                }
                if(sum%11 !== 1) {
                    return manager.getErrorMessage("IDCard InvaildNumber");
                }
            }
            return null;
        };

        manager.isDateString = function(str) {
            var formatter = (new jsx3.util.DateFormat("yyyyMMdd"));
            try {
                return formatter.format(formatter.parse(str)) == str;
            }
            catch (ex) {
                return false;
            }
        };

        manager.isNullValue = function(val) {
            return !!(val === "" || val === null || val === undefined);
        };

        /**
         * Utility function that determines if a string can be parsed as a non-negative (greater than or equal to 0)
         * floating point number.
         *
         * @param sNum {String} the string to test
         *
         * @return {boolean} <code>true</code> if the string can be successfully parsed as a non-negative floating point number
         */
        manager.isPositiveFloatingPoint = function(sNum) {
            return !isNaN(sNum) && sNum >= 0 && sNum < 2147483647;
        };

        /**
         * Utility function that determines if a string can be parsed as a non-negative (greater than or equal to 0),
         * non-floating point number.
         *
         * @param sNum {String} the string to test
         *
         * @return {boolean} <code>true</code> if the string can be successfully parsed as a non-negative, non-floating point number
         */
        manager.isPositiveNumeric = function(sNum) {
            return !isNaN(sNum) && sNum >= 0 && 
                Math.abs(sNum) == sNum && 
                Math.ceil(sNum) == sNum && sNum < 2147483647;
        };

        /**
         * Utility function that determines if a string can be parsed as a non-negative (greater than or equal to 0)
         * number (floating point or non-floating point).
         *
         * @param sNum {String} the string to test
         *
         * @return {boolean} <code>true</code> if the string can be successfully parsed as a non-negative number
         */
        manager.isNumeric = function(sNum) {
            return !isNaN(sNum);
        };
    }
);
